package com.buho29.rcmanager;

import java.util.Date;
import java.util.LinkedList;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.SpannableStringBuilder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.ToggleButton;

import com.buho29.rcmanager.bd.DatabaseAdapter;
import com.buho29.rcmanager.bd.TableAlarm;
import com.buho29.rcmanager.bd.TableDrive;
import com.buho29.rcmanager.bd.TableModel;
import com.buho29.rcmanager.bd.TablePower;
import com.buho29.rcmanager.bd.TablePowerItem;
import com.buho29.rcmanager.utils.Make;
import com.buho29.rcmanager.utils.Format;
import com.buho29.rcmanager.widget.Chrono;

public class ChronoView extends Activity {
	
	Chrono mChronometer;
	
    public static final String CMD="cmd";
    public static final int CMD_1 =1;

	private static final String STAT = "stat";
	private static final String ELAPSEDTIME = "elapsedTime";

	private static final String CURRENTTIME = "currentTime";
    
	private int mAlarmSg = 0;
	private ToggleButton mButtonPlay ;
	
	private DatabaseAdapter mDbAdapter;
	private TableDrive mDbTableDrive = new TableDrive();
	private TablePower mDbTablePower = new TablePower();

    private NotificationManager mNotificationManager;
	private PendingIntent alarmPendingIntent;
	private boolean mAlarmCalled;
	private AlarmManager alarmManager;
	private Intent alarmIntent;

	private Long mPowerId;
	private int mCmd;
	private ViewGroup mLayout;
	private TextView mTextAlarm;
	

    private int mStat ;
    private int mElapsedTime;
    private long mCurrentTime;
	
	private GenQueue<TableAlarm> mAlarms = new GenQueue<TableAlarm>();

	public static int ALARM_SG; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        mDbAdapter = DatabaseAdapter.getInstance(this); 
        mDbTableDrive.setSQLiteDatabase(mDbAdapter.getDatabase());
        mDbTablePower.setSQLiteDatabase(mDbAdapter.getDatabase());
     	
        // Get the notification manager serivce.
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        
		Bundle extras = getIntent().getExtras();            
		if(savedInstanceState != null){
			mCmd = savedInstanceState.getInt(CMD);
	       	mPowerId = savedInstanceState.getLong(TablePower.COL_ROW_ID);
	       	mStat = savedInstanceState.getInt(STAT);
	        mElapsedTime = savedInstanceState.getInt(ELAPSEDTIME);
	        mCurrentTime = savedInstanceState.getLong(CURRENTTIME);
		}else if(extras != null){
			mCmd = extras.getInt(CMD);
			mPowerId = extras.getLong(TablePower.COL_ROW_ID);
		}
		
		if(mCmd<1){
			finish();
			return;
		}
        
			
        setContentView(R.layout.chrono);
        
        mChronometer = (Chrono) findViewById(R.id.chrono);
        mChronometer.setOnChronoViewTickListener(new Chrono.OnChronoViewTickListener(){

			@Override
			public void onChronoViewTick(Chrono chronometer) {
				updateTextChrono();
			}
        	
        });
			
        
        mButtonPlay = (ToggleButton) findViewById(R.id.start);
        
        mButtonPlay.setOnClickListener(new View.OnClickListener() {
	        public void onClick(View v) {
	        	if(mButtonPlay.isChecked()){
	        		mChronometer.start();
	        		startAlarm(mAlarmSg*1000 - mChronometer.getElapsedTime());
	        	}else{
	        		mChronometer.pause();
	        		stopAlarm();
	        	}
	        }
	    });
        
        Button button = (Button) findViewById(R.id.end);
        button.setOnClickListener(new View.OnClickListener() {
	        public void onClick(View v) {
	        	saveDrive((int) mChronometer.getElapsedTime()/1000);
	    		
	        	if(checkAlarmModel()){
	            	makeDiaAlarmModels();
	            }else{
	            	setResult(Activity.RESULT_OK);
	            	finish();
	            }
	        }
	    });

        button = (Button) findViewById(R.id.reset);
        button.setOnClickListener(new View.OnClickListener() {
	        public void onClick(View v) {
	            reset();
	        }
	    });
        mLayout = (ViewGroup)findViewById(R.id.alarmLayout);
        mTextAlarm = (TextView)findViewById(R.id.alarmText);

    	alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
		alarmIntent = new Intent(AlarmReceiver.ACTION_ALARM);
		alarmPendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent,PendingIntent.FLAG_UPDATE_CURRENT);
        
       populateFields();
    }

    
    private void reset() {;
		mButtonPlay.setChecked(false);
	    mChronometer.reset();
	    mChronometer.setTextColor(Color.WHITE);
		mAlarmCalled = false;
		mNotificationManager.cancel(R.layout.chrono);
	    stopAlarm();
    }
    
    private void populateFields(){
    	
    	mDbTablePower.setId(mPowerId);
    	mDbTablePower.load();
        
    	mAlarmSg = mDbTablePower.getAlarm();
    	
        TableModel tm = new TableModel();
		tm.setSQLiteDatabase(mDbAdapter.getDatabase());
		tm.setId(mDbTablePower.getModelId());
		tm.load();
		
		TablePowerItem tpi = new TablePowerItem();
		tpi.setSQLiteDatabase(mDbAdapter.getDatabase());
    	tpi.setId(mDbTablePower.getPowerItemId());
    	tpi.load();
		
        setTitle(tm.getName()+">"+tpi.getName());
        
        reset();

        updateAlarmField();
        
        switch (mStat) {
		case Chrono.STATE_START:
			long realTime = new Date().getTime() - mCurrentTime;
			mChronometer.start((int) (mElapsedTime+realTime));
			startAlarm(mAlarmSg*1000 - mElapsedTime);
			mButtonPlay.setChecked(true);
			updateTextChrono();
			break;
		case Chrono.STATE_PAUSE:
			mChronometer.pause(mElapsedTime);
			updateTextChrono();
			break;

		case Chrono.STATE_STOP:
			break;

		default:
			if(checkAlarmModel()){
	        	makeDiaAlarmModels();
	        }	
			break;
		}
    }
    

	private void updateAlarmField() {
		if(mAlarmSg>0) {
        	mLayout.setVisibility(View.VISIBLE);
        	mTextAlarm.setText(Format.formatSecondsToString(mAlarmSg));
        }else{
        	mLayout.setVisibility(View.GONE);
        }
	}
    
    private void startAlarm(long alarmTime) {
    	if(mAlarmCalled || mAlarmSg<1 || mChronometer.getElapsedTime()/1000>mAlarmSg) return;
		
    	ALARM_SG =  mAlarmSg;
    	
		int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
		long timeToRefresh = SystemClock.elapsedRealtime() + alarmTime ;
		alarmManager.set(alarmType, timeToRefresh, alarmPendingIntent);
		
	}
    
    private void stopAlarm() {
    	alarmManager.cancel(alarmPendingIntent);
	}
    
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(CMD, mCmd);
        outState.putLong(TablePower.COL_ROW_ID, mPowerId);
        outState.putInt(STAT, mChronometer.getState());
        outState.putInt(ELAPSEDTIME, mChronometer.getElapsedTime());
        outState.putLong(CURRENTTIME, new Date().getTime());
    }
    
    
    
    @Override
    protected void onDestroy() {
    	super.onDestroy();	
		mNotificationManager.cancel(R.layout.chrono);
    }
    
    //menu  
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(0, Menu.FIRST,0, getString(R.string.addManual));
        menu.add(0, Menu.FIRST+1,0, getString(R.string.alarm));
        menu.add(0, Menu.FIRST+2,0, getString(R.string.addAccident));
        menu.add(0, Menu.FIRST+3,0, getString(R.string.delete_last_drive));
        return true;
    }    
    
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        switch(item.getItemId()) {
        case Menu.FIRST:
        	makeDiaDrive();
            return true;
        case Menu.FIRST+1:
        	makeDiaAlarm(mAlarmSg);
            return true;
        case Menu.FIRST+2:
        	MakeDiaAccidentCount();
        case Menu.FIRST+3:
        	mDbTableDrive.deleteLast(
        			mDbTablePower.getPowerItemId(),
        			mDbTablePower.getModelId()
        	);
            return true;
	    }        
        return super.onMenuItemSelected(featureId, item);
    }
    
    private void addAccidentCount() {
    	TableModel tm = new TableModel();
		tm.setSQLiteDatabase(mDbAdapter.getDatabase());
		tm.setId(mDbTablePower.getModelId());
		tm.load();
		tm.setAccident_count(tm.getAccident_count()+1);
		tm.save();
	}

	private void MakeDiaAccidentCount() {
    	new AlertDialog.Builder(ChronoView.this)
		.setIcon(R.drawable.alert_dialog_icon)
        .setTitle(R.string.addAccident)
        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
        	public void onClick(DialogInterface dialog, int whichButton) {
        		addAccidentCount();
        	}
        })
        .setNegativeButton(R.string.cancel,null).create().show();
	}

	private void makeDiaAlarmModels() {
		
		if(!mAlarms.hasItems())return;
		
		LayoutInflater factory = LayoutInflater.from(this);
		final View view = factory.inflate(R.layout.diatext, null);
		
		TextView tv = (TextView) view.findViewById(R.id.tv);
		
		final TableAlarm ta = mAlarms.dequeue();
		
		String text = "";
			
		switch (ta.getType()) {
			case TableAlarm.TYPE_TIME:
			text = getText(R.string.time)+" "+ta.getStep()+" "+getString(R.string.h);
			break;
		case TableAlarm.TYPE_DATE:
			text = getText(R.string.date)+" "+ta.getStep()+" "+getString(R.string.d);
			break;
		}
		
		tv.setText(
			Make.appendResult(new SpannableStringBuilder(),text,ta.getName() ,"")	
		);
		
		
		new AlertDialog.Builder(ChronoView.this)
		.setIcon(R.drawable.alert_dialog_icon)
        .setTitle(R.string.alarm)
        .setView(view)
        .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
        	public void onClick(DialogInterface dialog, int whichButton) {
        		ta.reset();
        		ta.save();
        		makeDiaAlarmModels();
        	}
        })
        .setNegativeButton(R.string.remenber,  new DialogInterface.OnClickListener() {
        	public void onClick(DialogInterface dialog, int whichButton) {
        		makeDiaAlarmModels();
        	}
        }).create().show();
		
	}
	
	private Boolean checkAlarmModel() {
		
		TableAlarm ta = new TableAlarm();
		ta.setSQLiteDatabase(mDbAdapter.getDatabase());
		Cursor cur = ta.fetchModel(mDbTablePower.getModelId());
		startManagingCursor(cur);
		
		for (int i = 0; i < cur.getCount(); i++) {
			cur.moveToPosition(i);
			
			TableAlarm ta1 = new TableAlarm();
			ta1.setSQLiteDatabase(mDbAdapter.getDatabase());
			ta1.loadCursor(cur);
			
			if(ta1.getTimeLeft()<1) mAlarms.enqueue(ta1);
		}
		
		return mAlarms.hasItems();
	}


	private void makeDiaAlarm(int alarm) {
		LayoutInflater factory = LayoutInflater.from(this);
		final View view = factory.inflate(R.layout.alarm, null);
		
		final Spinner hs = (Spinner) view.findViewById(R.id.hours);
		final Spinner ms = (Spinner) view.findViewById(R.id.min);
		final Spinner ss = (Spinner) view.findViewById(R.id.Seg);
        
		String[] str = Format.formatSecondsToString(alarm).split(":");
		
		hs.setSelection(Integer.parseInt(str[0]));
		ms.setSelection(Integer.parseInt(str[1]));
		ss.setSelection(Integer.parseInt(str[2]));
		
		new AlertDialog.Builder(ChronoView.this)
			.setIcon(R.drawable.alert_dialog_icon)
            .setTitle(R.string.alarm)
            .setView(view)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            	public void onClick(DialogInterface dialog, int whichButton) {
            		String h = (String) hs.getSelectedItem();
            		String m = (String) ms.getSelectedItem();
            		String s = (String) ss.getSelectedItem();
            		
            		int alarm = Format.formatStringToSeconds(h+":"+m+":"+s);
            		saveAlarm(alarm);
            	}
            })
            .setNegativeButton(R.string.cancel, null)
            .create().show();
	}
    
    private void makeDiaDrive() {
    	LayoutInflater factory = LayoutInflater.from(this);
		final View view = factory.inflate(R.layout.alarm, null);
		
		final Spinner hs = (Spinner) view.findViewById(R.id.hours);
		final Spinner ms = (Spinner) view.findViewById(R.id.min);
		final Spinner ss = (Spinner) view.findViewById(R.id.Seg);
        
		String[] str = Format.formatSecondsToString(0).split(":");
		
		hs.setSelection(Integer.parseInt(str[0]));
		ms.setSelection(Integer.parseInt(str[1]));
		ss.setSelection(Integer.parseInt(str[2]));
		
		new AlertDialog.Builder(ChronoView.this)
			.setIcon(R.drawable.alert_dialog_icon)
            .setTitle(R.string.addManual)
            .setView(view)
            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
            	public void onClick(DialogInterface dialog, int whichButton) {
            		String h = (String) hs.getSelectedItem();
            		String m = (String) ms.getSelectedItem();
            		String s = (String) ss.getSelectedItem();
            		
            		int sg = Format.formatStringToSeconds(h+":"+m+":"+s);
            		saveDrive(sg);
            		if(checkAlarmModel()){
    	            	makeDiaAlarmModels();
    	            }
            	}
            })
            .setNegativeButton(R.string.cancel, null).create().show();
	}
    
    private void saveDrive(int sg) {
    	if(sg < 1) {
    		Make.toast(this,getText(R.string.help_cero_seconds)).show();
    	}else {
    		
    		mDbTableDrive.setId(0L);
    		mDbTableDrive.setModelId(mDbTablePower.getModelId());
    		mDbTableDrive.setPowerItemId(mDbTablePower.getPowerItemId());
    		mDbTableDrive.setTime(sg);
    		mDbTableDrive.save();
    		
    		Make.toast(this,getText(R.string.saved)+" "+
    			Format.formatSecondsToString(sg)).show();
    	}
    }
    
    private void saveAlarm(int alarm) {
    	mDbTablePower.setAlarm(alarm);
    	mDbTablePower.save();
    	mAlarmSg = alarm;
    	updateAlarmField();
    }
    
    private void updateTextChrono() {
		if(!mAlarmCalled && mAlarmSg>0 && mChronometer.getElapsedTime()/1000>mAlarmSg){
			mChronometer.setTextColor(Color.RED);
			mAlarmCalled = true;
		}
	}

	public class GenQueue<E> {
    	  private LinkedList<E> list = new LinkedList<E>();

    	  public void enqueue(E item) {
    	    list.addLast(item);
    	  }

    	  public E dequeue() {
    	    return list.poll();
    	  }

    	  public boolean hasItems() {
    	    return !list.isEmpty();
    	  }

    	  public int size() {
    	    return list.size();
    	  }

    	  public void addItems(GenQueue<? extends E> q) {
    	    while (q.hasItems())
    	      list.addLast(q.dequeue());
    	  }
    }
    
}


